﻿using System;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.IO;
using ScarecrowLibrary.IO;
using ScarecrowLibrary.Network;

namespace Scarecrow_Network_Manager
{
    // TODO : [V:2.1.0.0]Gestione delle risorse di rete come stampanti, hdd etc

    /// <summary>
    /// Logica di interazione per ProfileWindow.xaml
    /// </summary>
    public partial class ProfileWindow : Window
    {
        #region Properties
        public string ProfilePath
        {
            get;
            private set;
        }
        #endregion

        #region Fields
        //private scNetworkProfile np;
        private scAdapterProfile[] profiles;
        #endregion

        #region Methods
        public ProfileWindow(string profilePath)
        {
            InitializeComponent();
            ProfilePath = profilePath;
        }
        #endregion

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //Inizializzazione dei controlli
            try
            {
                //Ciclo di inizializzazione dell'animazione del TabControl
                foreach (TabItem item in tbControl.Items)
                {
                    item.IsSelected = true;
                }
                (tbControl.Items[0] as TabItem).IsSelected = true;

                //Carico tutte le immagini
                string[] images = System.IO.Directory.GetFiles(System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) + @"\Images\Profiles\", "*.png");
                string[] userImages = System.IO.Directory.GetFiles(Global.ImagesPath, "*.png");
                images = images.Concat(userImages.AsEnumerable()).ToArray();
                scNetworkProfile np = null;

                //se profileName == null allora è un nuovo profilo, altrimenti carico da disco il profilo esistente
                if (!string.IsNullOrWhiteSpace(ProfilePath))
                {
                    //Carico da disco il profilo esistente
                    np = scSerializer.Deserialize(File.ReadAllBytes(ProfilePath)) as scNetworkProfile;
                    this.txtProfile.Text = np.Name;

                    //devo ottenere tutte le schede attive in questo momento
                    //e se per queste schede esiste già un profilo, lo associo
                    // i profili che si riferiscono a schede non presenti
                    // vengono ignorati e schede che non hanno ancora un profilo
                    // aggiunte!
                    this.profiles = new scAdapterProfile[Global.Nics.Length];
                    scAdapterProfile[] npProfiles = np.GetProfiles();
                    for (int i = 0; i < Global.Nics.Length; i++)
                    {
                        for (int j = 0; j < npProfiles.Length; j++)
                        {
                            if (Global.Nics[i].ConnectionName == npProfiles[j].NetworkAdapter)
                            {
                                this.profiles[i] = npProfiles[j];
                            }
                        }
                        if (this.profiles[i] == null)
                        {
                            this.profiles[i] = Global.Nics[i].ExportToProfile();
                        }
                    }
                }
                else
                {
                    //Creo i profili per ogni scheda attiva
                    this.profiles = new scAdapterProfile[Global.Nics.Length];
                    for (int i = 0; i < Global.Nics.Length; i++)
                    {
                        this.profiles[i] = Global.Nics[i].ExportToProfile();
                    }
                }

                foreach (string imagePath in images)
                {
                    Image image = Global.LoadImageFromPath(imagePath);
                    image.Source = Global.ResizeImage(image.Source, 64, 64);
                    image.Tag = imagePath;
                    image.Margin = new Thickness(3);
                    this.lstImages.Items.Add(image);
                    if (np != null && System.IO.Path.GetFileNameWithoutExtension(np.ImagePath) == System.IO.Path.GetFileNameWithoutExtension(imagePath))
                    {
                        this.lstImages.SelectedItem = image;
                    }
                }

                this.lstAdapters.ItemsSource = Global.Nics;
                this.lstAdapters.SelectedIndex = 0;
            }
            catch(Exception exc)
            {
                Global.NotifyCrash(exc);
            }
        }

        private void cmdClose_Click(object sender, RoutedEventArgs e)
        {
            ProfilePath = null;
            this.Close();
        }

        private void cmdSave_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (!Check())
                    return;

                scNetworkProfile np = new scNetworkProfile();
                //tutto bene
                np.Name = txtProfile.Text;
                np.ImagePath = (this.lstImages.SelectedItem as Image).Tag.ToString();

                //Aggiungo i profili
                foreach (scAdapterProfile p in profiles)
                {
                    np.AddAdapterProfile(p);
                }

                //salvo nel percorso specificato
                string path = Path.Combine(Global.ProfilesPath, txtProfile.Text);

                //Controllo che non ci sia già un altro profilo con le stesse impostazioni
                string[] files = System.IO.Directory.GetFiles(Global.ProfilesPath);
                foreach (string profileName in files)
                {
                    scNetworkProfile toCheck = scSerializer.Deserialize(File.ReadAllBytes(Path.Combine(Global.ProfilesPath, profileName))) as scNetworkProfile;

                    if (toCheck.Name == Properties.Resources.UnknowProfile)
                        continue;

                    toCheck.Name = np.Name;
                    toCheck.ImagePath = np.ImagePath;
                    if(np == toCheck || System.IO.File.Exists(path))
                        if (MessageBox.Show(Properties.Resources.ProfileOverwriting, Properties.Resources.Warning, MessageBoxButton.YesNo) == MessageBoxResult.No)
                        {
                            return;
                        }
                        else
                        {
                            break;
                        }
                }

                //se ProfilePath è vuoto, era un nuovo profilo!
                //Altrimenti lo cancello e salvo nel nuovo percorso
                if (!string.IsNullOrWhiteSpace(ProfilePath))
                {
                    //se il nuovo nome è diverso dal percorso del profilo, cancello quello vecchio e scrivo quello nuovo
                    System.IO.File.Delete(ProfilePath);
                }

                ProfilePath = path;

                //salvo nel nuovo percorso
                File.WriteAllBytes(ProfilePath, scSerializer.Serialize(np));
                this.Close();
            }
            catch (Exception exc)
            {
                Global.NotifyCrash(exc);
            }
        }

        private void lstAdapters_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                //carica le impostazioni associate a tale scheda, se è abilitata
                this.lblAdapter.Content = lstAdapters.SelectedItem;

                if (profiles != null && profiles.Length > 0)
                {
                    scAdapterProfile original = profiles[lstAdapters.SelectedIndex];
                    original.NetworkAdapter = lstAdapters.SelectedItem.ToString();
                    this.rbEnabled.IsChecked = original.Enabled;
                    this.rbDisabled.IsChecked = !original.Enabled;

                    this.rbDHCPIP.IsChecked = original.IsIPDhcp;
                    this.rbStaticIP.IsChecked = !original.IsIPDhcp;
                    if (!original.IsIPDhcp)
                    {
                        this.txtIPAddr.Text = original.IPAddress;
                        this.txtSubnet.Text = original.SubnetMask;
                        this.txtGateway.Text = original.Gateway;
                    }
                    else
                    {
                        this.txtIPAddr.Text = this.txtSubnet.Text = this.txtGateway.Text = "";
                    }

                    this.rbDHCPDNS.IsChecked = original.IsDNSDhcp;
                    this.rbStaticDNS.IsChecked = !original.IsDNSDhcp;
                    if (!original.IsDNSDhcp)
                    {
                        this.txtDNS1.Text = original.DNS1;
                        this.txtDNS2.Text = original.DNS2;
                    }
                    else
                    {
                        this.txtDNS1.Text = this.txtDNS2.Text = "";
                    }
                }
            }
            catch (Exception exc)
            {
                Global.NotifyCrash(exc);
            }
        }

        #region ErrorCheck
        bool Check()
        {
            try
            {
                //Controllo il profilo di rete
                bool error = false;
                this.lblProfile.Foreground = Brushes.SteelBlue;
                //Controllo nome
                if (string.IsNullOrWhiteSpace(txtProfile.Text))
                {
                    //segnalare errore
                    this.lblProfile.Foreground = Brushes.Red;
                    this.tbHome.IsSelected = true;
                    error = true;
                }

                //Rimuovo i caratteri non validi
                char[] invalidChars = System.IO.Path.GetInvalidFileNameChars();
                string name = txtProfile.Text;
                foreach (char ch in invalidChars)
                {
                    name = name.Replace(new string(new char[] { ch }), "");
                }

                //Controllo immagine
                this.lblImage.Foreground = Brushes.SteelBlue;
                if (this.lstImages.SelectedItem == null)
                {
                    this.lblImage.Foreground = Brushes.Red;
                    this.tbHome.IsSelected = true;
                    error = true;
                }

                //Controllo tutti i profili delle singole schede
                //confronto i profili e segnalo un errore
                //se due profili differenti condividono le stesse impostazioni
                //segnalo l'errore
                for (int i = 0; i < this.profiles.Length; i++)
                {
                    //Seleziono il profilo
                    this.lstAdapters.SelectedIndex = i;
                    //effettuo il controllo
                    if (IPCheck() || SubnetCheck() || GatewayCheck() || DNS1Check() || DNS2Check() || error || string.IsNullOrWhiteSpace(lblAdapter.Content.ToString()))
                    {
                        //se non lo supero, esco
                        return false;
                    }
                }

                //Se arrivo qui, tutti i profili hanno superato il controllo
                //controllo che non ci siano 2 profili uguali
                for (int i = 0; i < this.profiles.Length - 1; i++)
                {
                    for (int j = 1; j < this.profiles.Length; j++)
                    {
                        if (i != j)
                        {
                            scAdapterProfile a = this.profiles[i];
                            scAdapterProfile b = this.profiles[j];
                            string temp = a.NetworkAdapter;
                            a.NetworkAdapter = b.NetworkAdapter;
                            if (a == b && (!a.IsIPDhcp || !a.IsDNSDhcp))
                            {
                                MessageBox.Show("Impossibile applicare le stesse impostazioni a due schede attive contemporaneamente. Verificare la configurazione impostata!");
                                a.NetworkAdapter = temp;
                                return false;
                            }
                            a.NetworkAdapter = temp;
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                Global.NotifyCrash(exc);
            }
            return true;
        }
        private void rbStaticIP_Checked(object sender, RoutedEventArgs e)
        {
            try
            {
                this.grpbIP.IsEnabled = true;
                this.rbStaticDNS.IsChecked = true;
                this.rbDHCPDNS.IsEnabled = false;
                this.profiles[lstAdapters.SelectedIndex].IsIPDhcp = false;
            }
            catch { }
        }

        private void rbDHCPIP_Checked(object sender, RoutedEventArgs e)
        {
            try
            {
                this.grpbIP.IsEnabled = false;
                if (this.rbDHCPDNS != null)
                    this.rbDHCPDNS.IsEnabled = true;
                this.profiles[lstAdapters.SelectedIndex].IPAddress = this.profiles[lstAdapters.SelectedIndex].SubnetMask = this.profiles[lstAdapters.SelectedIndex].Gateway = "";
                this.profiles[lstAdapters.SelectedIndex].IsIPDhcp = true;
            }
            catch { }
        }

        private void rbDHCPDNS_Checked(object sender, RoutedEventArgs e)
        {
            try
            {
                this.grpbDNS.IsEnabled = false;
                this.profiles[lstAdapters.SelectedIndex].DNS1 = this.profiles[lstAdapters.SelectedIndex].DNS2 = "";
                this.profiles[lstAdapters.SelectedIndex].IsDNSDhcp = true;
            }
            catch { }
        }

        private void rbStaticDNS_Checked(object sender, RoutedEventArgs e)
        {
            try
            {
                this.grpbDNS.IsEnabled = true;
                this.profiles[lstAdapters.SelectedIndex].IsDNSDhcp = false;
            }
            catch { }
        }
        private void rbDisabled_Checked(object sender, RoutedEventArgs e)
        {
            try
            {
                this.IPGrid.IsEnabled = this.DNSGrid.IsEnabled = false;
                this.profiles[lstAdapters.SelectedIndex].Enabled = false;
            }
            catch { }
        }

        private void rbEnabled_Checked(object sender, RoutedEventArgs e)
        {
            try
            {
                this.IPGrid.IsEnabled = this.DNSGrid.IsEnabled = true;
                this.profiles[lstAdapters.SelectedIndex].Enabled = true;
            }
            catch { }
        }
        bool IPCheck()
        {
            bool error = false;
            try
            {
                string s = this.txtIPAddr.Text.Trim();
                if ((bool)this.rbStaticIP.IsChecked)
                {
                    if (!string.IsNullOrWhiteSpace(s))
                    {
                        IPAddress ip = IPAddress.Parse(s);
                        this.profiles[lstAdapters.SelectedIndex].IPAddress = ip.ToString();
                        this.lblIP.Foreground = Brushes.SteelBlue;
                    }
                    else
                    {
                        this.lblIP.Foreground = Brushes.Red;
                        error = true;
                    }
                }
                else
                {
                    this.profiles[lstAdapters.SelectedIndex].IPAddress = "";
                }
            }
            catch
            {
                this.lblIP.Foreground = Brushes.Red;
                error = true;
            }
            return error;
        }
        bool SubnetCheck()
        {
            bool error = false;
            try
            {
                string s = this.txtSubnet.Text.Trim();
                if ((bool)this.rbStaticIP.IsChecked)
                {
                    if (!string.IsNullOrWhiteSpace(s))
                    {
                        IPAddress ip = IPAddress.Parse(s);
                        this.profiles[lstAdapters.SelectedIndex].SubnetMask = ip.ToString();
                        this.lblSubnet.Foreground = Brushes.SteelBlue;
                    }
                    else
                    {
                        this.lblSubnet.Foreground = Brushes.Red;
                        error = true;
                    }
                }
                else
                {
                    this.profiles[lstAdapters.SelectedIndex].SubnetMask = "";
                }
            }
            catch
            {
                this.lblSubnet.Foreground = Brushes.Red;
                error = true;
            }
            return error;
        }
        bool GatewayCheck()
        {
            bool error = false;
            try
            {
                string s = this.txtGateway.Text.Trim();
                if (!string.IsNullOrWhiteSpace(s))
                {
                    IPAddress ip = IPAddress.Parse(s);
                    this.profiles[lstAdapters.SelectedIndex].Gateway = ip.ToString();
                    this.lblGateway.Foreground = Brushes.SteelBlue;
                }
                else
                {
                    this.profiles[lstAdapters.SelectedIndex].Gateway = "";
                }
            }
            catch
            {
                if (!string.IsNullOrWhiteSpace(this.profiles[lstAdapters.SelectedIndex].Gateway))
                {
                    this.lblGateway.Foreground = Brushes.Red;
                    error = true;
                }
                else
                {
                    this.lblGateway.Foreground = Brushes.SteelBlue;
                }
            }
            return error;
        }
        bool DNS1Check()
        {
            bool error = false;
            try
            {
                string s = this.txtDNS1.Text.Trim();
                if ((bool)this.rbStaticDNS.IsChecked)
                {
                    if (!string.IsNullOrWhiteSpace(s))
                    {
                        IPAddress ip = IPAddress.Parse(s);
                        this.profiles[lstAdapters.SelectedIndex].DNS1 = ip.ToString();
                        this.lblDNS1.Foreground = Brushes.SteelBlue;
                    }
                    else
                    {
                        this.profiles[lstAdapters.SelectedIndex].DNS1 = "";
                    }
                }
                else
                {
                    this.profiles[lstAdapters.SelectedIndex].DNS1 = "";
                }
            }
            catch
            {
                if (!string.IsNullOrWhiteSpace(this.profiles[lstAdapters.SelectedIndex].Gateway))
                {
                    this.lblDNS1.Foreground = Brushes.Red;
                    error = true;
                }
            }
            return error;
        }
        bool DNS2Check()
        {
            bool error = false;
            try
            {
                string s = this.txtDNS2.Text.Trim();
                if ((bool)this.rbStaticDNS.IsChecked)
                {
                    if (!string.IsNullOrWhiteSpace(s))
                    {
                        IPAddress ip = IPAddress.Parse(s);
                        this.profiles[lstAdapters.SelectedIndex].DNS2 = ip.ToString();
                        this.lblDNS2.Foreground = Brushes.SteelBlue;
                    }
                    else
                    {
                        this.profiles[lstAdapters.SelectedIndex].DNS2 = "";
                    }
                }
                else
                {
                    this.profiles[lstAdapters.SelectedIndex].DNS2 = "";
                }
            }
            catch
            {
                if (!string.IsNullOrWhiteSpace(this.profiles[lstAdapters.SelectedIndex].Gateway))
                {
                    this.lblDNS2.Foreground = Brushes.Red;
                    error = true;
                }
            }
            return error;
        }
        private void txtIPAddr_TextChanged(object sender, TextChangedEventArgs e)
        {
            IPCheck();
        }

        private void txtSubnet_TextChanged(object sender, TextChangedEventArgs e)
        {
            SubnetCheck();
        }

        private void txtGateway_TextChanged(object sender, TextChangedEventArgs e)
        {
            GatewayCheck();
        }

        private void txtDNS1_TextChanged(object sender, TextChangedEventArgs e)
        {
            DNS1Check();
        }

        private void txtDNS2_TextChanged(object sender, TextChangedEventArgs e)
        {
            DNS2Check();
        }
        #endregion

        private void cmdRefreshAdapters_Click(object sender, RoutedEventArgs e)
        {
            cmdRefreshAdapters.Content = Properties.Resources.Waiting;
            cmdRefreshAdapters.UpdateLayout();
            this.IsEnabled = false;
            Global.Nics = scNetworkAdapter.GetAllInterfaces();
            this.IsEnabled = true;
            cmdRefreshAdapters.Content = Properties.Resources.Refresh;
        }

        private void cmdAddImage_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                using (System.Windows.Forms.OpenFileDialog ofd = new System.Windows.Forms.OpenFileDialog())
                {
                    ofd.Filter = "Icon Files|*.png";
                    ofd.CheckFileExists = ofd.CheckPathExists = true;
                    ofd.ShowDialog();
                    if (!string.IsNullOrWhiteSpace(ofd.FileName))
                    {
                        string imagePath = System.IO.Path.Combine(Global.ImagesPath, ofd.SafeFileName);
                        System.IO.File.Copy(ofd.FileName, imagePath, true);
                        Image image = Global.LoadImageFromPath(imagePath);
                        image.Source = Global.ResizeImage(image.Source, 64, 64);
                        image.Tag = imagePath;
                        image.Margin = new Thickness(3);
                        this.lstImages.Items.Add(image);
                    }
                }
            }
            catch (Exception exc)
            { Global.NotifyCrash(exc); }
        }

        private void cmdRemoveImage_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (lstImages.SelectedItem != null)
                {
                    string path = (lstImages.SelectedItem as Image).Tag.ToString();
                    if (Global.ImagesPath == System.IO.Path.GetDirectoryName(path))
                    {
                        System.IO.File.Delete(path);
                        lstImages.Items.Remove(lstImages.SelectedItem);
                    }
                }
            }
            catch (Exception exc)
            { Global.NotifyCrash(exc); }
        }
    }
}
